#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <glib.h> // GString, g_slice_new
#include <mysql.h>
#include "syncup_db.h"

MYSQL *mysql;
MYSQL_RES *results;
MYSQL_ROW record;

struct syncup_db_entry e;
struct syncup_db_cursor *cursor;
union syncup_db_collection *collection;

const char *remote_db_path = "/home/israkir/Desktop/mysql-embedded/remote/syncupremotedb/";

void act(struct syncup_db_entry *e, int inode, int parent, char* name, 
	long timestamp, char* checksum, int flag) {
	if (flag == 0) {
		e->parent = parent;
		e->name = name;
		e->timestamp = timestamp;
		strncpy(e->checksum, checksum, 20);
	} else if (flag == 1) {
		e->inode = inode;
		e->parent = parent;
		e->name = name;
		e->timestamp = timestamp;
		strncpy(e->checksum, checksum, 20);
	}
}

void out(char *db) {
	if (strcmp(db, "1") == 0)
		mysql_query(mysql, 
			"SELECT inode, parent, name, timestamp, checksum "
			"FROM syncupremotedb.syncup");
	else if (strcmp(db, "0") == 0)
		mysql_query(mysql, 
			"SELECT inode, parent, name, timestamp, checksum "
			"FROM syncuplocaldb.syncup");
		
    results = mysql_store_result(mysql);
    
    while((record = mysql_fetch_row(results))) {
        printf("%s - %s - %s - %s - %s\n", record[0], record[1], 
        	record[2], record[3], record[4]);
	}
    mysql_free_result(results);
}

void print_usage() {
	printf("\nUsage:\n======\n"
		"Output all tuples in local db: ./dbtester out 0\n"
		"Output all tuples in remote db: ./dbtester out 1\n"
		"Insert new tuple to local db: "
		"./dbtester ins 0 [parent] [name] [timestamp] [checksum]\n"
		"Insert new tuple to remote db: "
		"./dbtester ins 1 [parent] [name] [timestamp] [checksum]\n"
		"Delete tuple in local db: ./dbtester del 0 [inode]\n"
		"Delete tuple in remote db: ./dbtester del 1 [inode]\n"
		"Update tuple in local: "
		"./dbtester upt 0 [inode] [parent] [name] [timestamp] [checksum] [option]\n"
		"Update tuple in remote: "
		"./dbtester upt 1 [inode] [parent] [name] [timestamp] [checksum] [option]\n"
		"Check for moved tuples: ./dbtester mov\n"
		"Check for modified tuples: ./dbtester mod\n"
		"Check for created tuples: ./dbtester cre\n"
		"Check for removed tuples: ./dbtester rem\n\n");
}

int main(int argc, char *argv[]) {
	
	syncup_db_init("my.cnf", "./data");
	
	attach_remote_db(remote_db_path);
	
	collection = g_slice_new(union syncup_db_collection);
	
	if (argc < 2) {
		print_usage();
		return -1;
	}
	
	if (strcmp(argv[1], "out") == 0) {
		out(argv[2]);
		
	} else if (strcmp(argv[1], "ins") == 0) {
		act(&e, 0, atoi(argv[3]), argv[4], atoi(argv[5]), argv[6], 0);
		int to = atoi(argv[2]);
		insert_new_tuple(&e, to, 0);
		out(argv[2]);
		
	} else if (strcmp(argv[1], "del") == 0) {
		int from = atoi(argv[2]);
		delete_tuple(atoi(argv[3]), from);
		out(argv[2]);
		
	} else if (strcmp(argv[1], "upt") == 0) {
		int option = atoi(argv[7]);
		int in = atoi(argv[2]);
		act(&e, atoi(argv[3]), atoi(argv[4]), argv[5], atoi(argv[6]), 
			argv[7], 1);
		update_tuple(&e, option, in);
		out(argv[2]);
		
	} else if (strcmp(argv[1], "mov") == 0) {
		cursor = store_moved_tuples_result();
		printf("\nlocal.inode\tlocal.parent\tremote.parent\n");
		while (syncup_fetch_row(cursor, collection)) {
			printf("%d\t\t%d\t\t%d\n", collection->moved.inode, 
				collection->moved.from, collection->moved.to);
		}
		syncup_free_result(cursor);
		
	} else if (strcmp(argv[1], "mod") == 0) {
		cursor = store_modified_tuples_result();
		printf("\nlocal.inode\n");
		while (syncup_fetch_row(cursor, collection)) {
			printf("%d\n", collection->modified.inode);
		}
		syncup_free_result(cursor);
		
	} else if (strcmp(argv[1], "cre") == 0) {
		cursor = store_created_tuples_result();
		printf("\nlocal.inode\n");
		while (syncup_fetch_row(cursor, collection)) {
			printf("%d\n", collection->created.inode);
		}
		syncup_free_result(cursor);
		
	} else if (strcmp(argv[1], "rem") == 0) {
		cursor = store_removed_tuples_result();
		printf("\nremote.inode\n");
		while (syncup_fetch_row(cursor, collection)) {
			printf("%d\n", collection->removed.inode);
		}
		syncup_free_result(cursor);
		
	} else {
		print_usage();
		return -1;
	}  

	printf("\n");
	
    return 0;    
}
